package jiggle;

import java.util.Enumeration;
import java.util.Vector;


public class ForceModel {

	protected Graph graph = null;
    // commented below, since it does not seem to be used
	//protected double preferredEdgeLength;

	private Vector<ForceLaw> forceLaws = new Vector<ForceLaw> ();
	private Vector<ForceLaw> constraints = new Vector<ForceLaw> ();

	public ForceModel (Graph g) {graph = g;}

	//double getPreferredEdgeLength () {return preferredEdgeLength;}
	//void setPreferredEdgeLength (double k) {preferredEdgeLength = k;}

	public void addForceLaw (ForceLaw fl) {forceLaws.addElement (fl);}
	public void removeForceLaw (ForceLaw fl) {forceLaws.removeElement (fl);}

	public void addConstraint (ForceLaw c) { constraints.addElement (c);}
	public void removeConstraint (ForceLaw c) {constraints.removeElement (c);}
	public boolean hasConstraints() {return !constraints.isEmpty();}
	
	private void initGradient(double[][] gradient) {
        int n = graph.getNumberOfVertices();
        int d = graph.getDimensions();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < d; j++) {
                gradient[i][j] = 0;
            }
            graph.vertices.get(i).gradientNdx = i;
        }
    }

	void getNegativeGradient(double[][] negativeGradient) {
        initGradient(negativeGradient);
        for (Enumeration en = forceLaws.elements(); en.hasMoreElements();) {
            ForceLaw curFL = (ForceLaw) en.nextElement();
            curFL.apply(negativeGradient);
            
            // uncomment to debug
            //tstNegativeGradient(negativeGradient, curFL);
        }
    }

	void getPenaltyVector(double[][] penaltyVector) {
        initGradient(penaltyVector);
        for (Enumeration en = constraints.elements(); en.hasMoreElements();) {
            ((ForceLaw) (en.nextElement())).apply(penaltyVector);
        }
    }
	
    @SuppressWarnings("unused")
	private void tstNegativeGradient(double[][] negativeGradient, ForceLaw curFL) {
        int n = graph.getNumberOfVertices();
        int d = graph.getDimensions();
        boolean isValid = true;
        
        for (int i = 0; i < n; i++) {
        	for (int j = 0; j < d; j++) {
                if (Double.isNaN(negativeGradient[i][j])) {
                    isValid = false;
    			    System.err.println("ERR: PATCHING NG: " + negativeGradient[i][j]);
                    negativeGradient[i][j] = 0; // PATCHWORK
                }
        	}
        }
        if (!isValid) {
        	System.err.println("Invalid negativeGradient: " + curFL.getClass());
            //for (int i = 0; i < n; i++) {
        	//	for (int j = 0; j < d; j++) {
        	//	    System.err.print(negativeGradient[i][j] + "   ");
        	//	}
        	//    System.err.println("");
            //}
            //throw new RuntimeException("");
        }
    }


}